/*
  This file is part of jTopaz.
  http://gcl.cis.udel.edu/projects/jtopaz
  Copyright (C) 2009 University of Delaware

  jTopaz is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  jTopaz is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of                                                        
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with jTopaz.  If not, see <http://www.gnu.org/licenses/>.
*/

package jTopaz;

import java.applet.Applet;
import org.globus.ftp.GridFTPClient;
import org.globus.ftp.FTPClient;
import org.globus.ftp.FileRandomIO;
import org.ietf.jgss.GSSCredential;
import java.io.File;
import org.globus.gsi.GlobusCredential;
import org.globus.gsi.gssapi.GlobusGSSCredentialImpl;
import java.util.LinkedList;
import org.globus.ftp.MlsxEntry;
import java.lang.Runtime;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.globus.tools.proxy.GridProxyInit;
import org.globus.ftp.HostPort;
import java.net.*;
import java.util.*;
import java.io.*;
import java.nio.*;

/**
   Patrick McClory.
   This class wraps up CoG functionality into one object.  Creates threads for creating/authenticating clients.  Creates threads for transfers.  Maintains a queue of transfers.  Contains methods to see if threads have completed execution.
*/
public class GridFTPClientWrapper extends Applet {


    public void init() {
	super.init();	
    }
	
    //private fields - I don't think I'm using all of these anymore, so should be cleaned up.
    private GridFTPClient infoClient;
    private FTPClient infoAnonClient;
    private GridFTPClient transferClient;
    private FTPClient transferAnonClient;
    private boolean inProgress=false;
    private double speed=0;
    private double progress=0;
    private LocalFileMonitor localMonitor=null;
    private DownloadThread downloadTransfer;
    private String transferName;
    private LinkedList<String[]> transferQueue=new LinkedList<String[]>();
    private LinkedList<String[]> finishedJobs=new LinkedList<String[]>();
    private boolean loggedIn=false;
    private LoginThread loginComponent;
    private GridFTPClient uploadClient;
    private FTPClient uploadAnonClient;
    private RemoteFileMonitor remoteMonitor=null;
    private String uploadName;
    //0 for download, 1 for upload
    private int transferType;
    private UploadThread uploadTransfer;
    private GSSCredential cred = null;
    private MyProxyThread mpThread;
    private LoginThread transferLoginThread;
    private LoginThread uploadLoginThread;
    //private boolean infoReady;
    private boolean tAuthStarted=false;
    private boolean uAuthStarted=false;
    private boolean infoReady=false;
    private boolean transferReady=false;
    private boolean uploadReady=false;
    private boolean firstTransfer;
    private boolean firstUpload;
    private int transferCount=0;
    private String[] currentTransfer;
    private String serverStore;
    private int serverStorePort;
    private ListThread listT;
    private boolean connected=false;
    private boolean canceled=false;
	
	
	
    public boolean isConnected() {
	return connected;	
    }
	
    public void setConnected(boolean value) {
	connected=value;
    }
    /**
       Creates a MyProxyThread and starts it's execution.  This handles logging on to the myProxy server.
       @param String myProxyHost the name of the myproxy server you want to connect to.
    */
    public void myProxyLogin(String myProxyHost, String username, String password) {
		
	mpThread = new MyProxyThread(myProxyHost, username, password);
	mpThread.start();
	System.out.println("thread started?");
		
    }
	
    /**
       Gets the status of logging onto the myproxy server
       @return "success" if successfully logged on and obtained credential
    */
    public String getMyProxyStatus() {
	if (mpThread.getStatus() == "success") {
	    cred = mpThread.getCred();	
	}
	System.out.println(mpThread.getStatus());
	return mpThread.getStatus();	
    }
	
    public void credFromFile(String fileName) {
		
	try {
	    GlobusCredential globCred = new GlobusCredential(fileName);
	    System.out.println("creating cred");
	    this.cred = new GlobusGSSCredentialImpl(globCred, GSSCredential.INITIATE_AND_ACCEPT);
	    System.out.println("done");
	}
	catch (Exception e) {
	    System.out.println(e);
	}
    }
    
    /**
       Starts the login thread of the info client
       @param host the name of the host to connect to
       @param pport the port num to connect to.
    */
    public void remoteLogin(String host, int pport) {
	System.out.println("port in remoteLogin = " + pport);
	loginComponent = new LoginThread(host, pport, cred);
	System.out.println("starting remote login thread?");
	loginComponent.start();
	serverStore = host;
	serverStorePort = pport;
	System.out.println("returning");
    }
	
    /**Starts the login thread of the transfer client.
       @param host the name of the host to connect to.
       @param pport the port num to connect to.
    */
    public void transferClientLogin(String host, int pport) {
	System.out.println("trying to create the transfer client");
	transferLoginThread = new LoginThread(host, pport, cred);
	transferLoginThread.start();
		
    }
	
    /**Starts the login thread of the upload client.
       @param host the name of the host to connect to.
       @param pport the port num to connect to.
    */
    public void uploadClientLogin(String host, int pport) {
	uploadLoginThread = new LoginThread(host, pport, cred);
	uploadLoginThread.start();
    }
	
    /**
       Gets the status of the info client log on thread.
       @return "success" if successfully logged on.  "failed" if there was an error.  Will be null if not finished executing.
    */	
    public String getLoginStatus() {
	System.out.println("trying to get login status????\n");
	if(loginComponent == null) {
	    System.out.println("WTF?");	
	}
	return loginComponent.getStatus();	
    }
	
    /**
       Gets the status of the transfer client log on thread.
       @return "success" if successfully logged on.  "failed" if there was an error.  Will be null if not finished executing.
    */	
    public String getTransferClientStatus() {
		
	if (transferLoginThread != null) {
	    return transferLoginThread.getStatus();
	}
	else {
	    return "null";
	}
    }
	
    /**
       Gets the status of the upload client log on thread.
       @return "success" if successfully logged on.  "failed" if there was an error.  Will be null if not finished executing.
    */	
    public String getUploadClientStatus() {
		
		
	return uploadLoginThread.getStatus();
    }
	
	
    /*
      These upcoming methods are essentially identical to the last 3, should go with one or the other.  and delete whichever one you don't use.
    */
	
    /**
       Returns whether or not this object is ready to handle upload transfers.
       @return true if it can.
    */
    public boolean isUploadReady() {
	try{
	    if (uploadLoginThread.getStatus() == "success") {
		uploadReady = true;	
	    }
		
		
	    return uploadReady;
	}
	catch (Exception e) {
	    return false;
	}
    }
	
    /**
       Returns whether or not this object is ready to handle transfers (downloads).
       @return true if it can
    */
    public boolean isTransferReady() {
	try {
	    if (transferLoginThread.getStatus() == "success") {
		transferReady = true;	
	    }
	    else {
		transferReady=false;
	    }
	    return transferReady;
	}
	catch (Exception e) {
	    return false;
	}
    }
	
    /**
       Returns whether or not this object is ready to obtain remote info (for directory browsing).
       @return true if it can
    */
    public boolean isInfoReady() {
	try {
	    if (loginComponent.getStatus() == "success") {
		infoReady = true;	
	    }
	    return infoReady;
	}
	
	catch (Exception e) {
	    return false;
	}
    }
	
    /**
       Sets the transfer client as the client created during the execution of the transfer login thread.
    */
    public void setTransferClient() {
	if(cred!=null){
	    transferClient = transferLoginThread.getClient();
	}
	else{
	    transferAnonClient = transferLoginThread.getAnonClient();
	}
	//change this later to something else
	firstTransfer = false;	
    }
	
    /**
       Sets the upload client as the client created during the execution of the upload login thread.
    */
    public void setUploadClient() {
	if(cred!=null){
	    uploadClient = uploadLoginThread.getClient();
	}
	else{
	    uploadAnonClient = uploadLoginThread.getAnonClient();
	}
		
    }
	
    /**
       Returns whether or not this is the first transfer.
    */
    public boolean isFirstTransfer() {
	return firstTransfer;
    }
	
    /**
       Returns whether or not this is the first upload.
    */
    public boolean isFirstUpload() {
	return firstUpload;	
    }
	
	
    public String makeDir(String dir) {
	try {
	    if(infoClient!=null){
		infoClient.makeDir(dir);
	    }
	    else{
		infoAnonClient.makeDir(dir);
	    }
	    return "success";	
	}
	catch (Exception e) {
	    System.out.println(e);
	    return "error";
	}
    }
    //update
    /**
       Updates the info client.  Resets the server into passive mode, and the client into active mode.
       @return "success" if successful.
    */
    public String update() {
	
	if (infoClient == null) {
	    infoClient = loginComponent.getClient();
	}
	if(infoAnonClient == null){
	    infoAnonClient = loginComponent.getAnonClient();
	}

	try {
	    if(cred!=null){
		infoClient.setPassive();
		infoClient.setLocalActive();
		System.out.println("set client active/server passive passed!");
	    }
	    else{
		infoAnonClient.setPassive();
		infoAnonClient.setLocalActive();
		System.out.println("set client active /server passive for anonymous passed");
	    }

	    return "success";
	}
	catch (Exception e) {
	    return e.toString();
	}
    }

    public boolean transferCanceled() {
	return canceled;	
    }
	
    public void reconnectTransfer() {
	transferClientLogin(serverStore, serverStorePort);
	canceled=false;	
    }
    /**
       Calls the GridFTPClient list method to get the contents of the current dir.
       @return an array of objects corresponding the contents.
    */
    public void list() {
	System.out.println("list() called");
	try {
	    if(infoClient!=null){
		listT = new ListThread(infoClient);
	    }
	    else{
		listT = new ListThread(infoAnonClient);
	    }
	    listT.start();
	    //return contents;
	}

	catch (Exception e) {
	    System.out.println(e);
	    //return null;
	}
    }

    public boolean listComplete() {
	return listT.listComplete();	
    }
	
    public String getListStatus() {
	return listT.getStatus();	
    }
	
    public Object[] getContents() {
	if(listT==null){
	    System.out.println("getContents: listT==null");
	}
	else{
	    System.out.println("well listTisnt null");
	}
	return listT.getContents();
    }
    /**
       Adds a new transfer to the transfer queue.
       @param command the name of the command (either "upload" or "download")l
       @param remoteFile the full name (path) of the remoteFile to upload to or download from.
       @param localFile the full name (path) of the local file to upload from or download to.
    */
    public void addToQueue(String command, String remoteFile, String localFile) {
	String[] job = new String[4];
	job[0] = command;
	job[1] = remoteFile;
	job[2] = localFile;
	job[3] = new Integer(transferCount).toString();
	transferCount++;
	transferQueue.add(job);
	System.out.println("job added to the queue");
    }

    /**
       Returns whether or not the next transfer is ready to take place.  Makes sure no job is currently in progress, and there is another job to run.
    */
    public boolean queueReady() {
	//System.out.println("in here");
	if (inProgress) {
	    return false;
	}
	//check if there is a command to run
	else if ((transferQueue.size() > 0) && isTransferReady()) {
	    System.out.println("queue size: " + transferQueue.size());
	    return true;
	}
	else 
	    return false;
    }

    /**
       Starts the next transfer in the queue.
    */
    public void StartTransfer() {
	String[] command = transferQueue.removeFirst();
	currentTransfer = command;

	System.out.println("in here?");
	System.out.println(command[0]);
	System.out.println(command[1]);
	System.out.println(command[2]);

	if(command[0].compareTo("download") == 0 || command[0].compareTo("downloadp") == 0 || command[0].compareTo("downloadS") == 0) {
	    boolean pimped = false;
	    boolean serverActive = false;
	    if(command[0].endsWith("p")){
		    pimped = true;
	    }
	    else if(command[0].endsWith("S")){
		serverActive = true;
	    }
	    File localFile = new File(command[2]);
	    System.out.println("calling download with c1= " + command[1] + " localFile= " + localFile + " pimped " + pimped + " sAct = " + serverActive);
	    download(command[1], localFile, pimped, serverActive);
	}
		
	else if (command[0].compareTo("upload") == 0) {
	    //System.out.println(command[1]);
	    //System.out.println(command[2]);
	    File localFile = new File(command[1]);
	    //System.out.println("wtf is going on?");
	    upload(command[2], localFile);	
	}
    }
    
    //I think this should be changed to private.
    /**
       Creates a DownloadThread object and begins it's execution.  Also creates a LocalFileMonitor and begins it's execution.
       @param remoteFileName the name of the remoteFile to download (full path).
       @param localFile the file object to download to.
       @return "success" if the download was successfully started.    */
    public String download(String remoteFileName, File localFile, boolean pimped, boolean serverActive) {

	if (! isTransferReady() ) {
	    System.out.println("not ready to transfer");
	    return "not ready";	
	}
		
	try {
	    inProgress = true;
	    transferType =0;
	    //client.get(remoteFileName, localFile);
	    
	    transferName = localFile.getName();
	    
	    //for now just overwrite it, get rid of this for a check later
	    if(localFile.exists()) {
		localFile.delete();
	    }

	    localFile.createNewFile();
	    
	    long remoteSize;
	    if(infoClient!=null){
		remoteSize = infoClient.getSize(remoteFileName);
	    }
	    else {
		remoteSize = infoAnonClient.getSize(remoteFileName);
	    }


	    localMonitor = new LocalFileMonitor(localFile.getPath(), remoteSize);

	    System.out.println("transferClient = " + transferClient);
	    System.out.println("transferAnonClient = " + transferAnonClient);

	    if(transferClient!=null){
		if(serverActive || pimped){
		    int portNumber = randPort();
		    if(pimped){
			transferClient.setDCStack("phoebus");
			System.out.println("DC stack set for phoebus. using myproxy. server Active.");
		    }
		    transferClient.setLocalPassive(portNumber, 0);
		    InetAddress externIP = getIP();
		    HostPort hp = new HostPort(externIP, portNumber);
		    transferClient.setActive(hp);
		}
		else{
		    transferClient.setPassive();
		    transferClient.setLocalActive();
		}
		downloadTransfer = new DownloadThread(transferClient, localFile, remoteFileName, remoteSize);
	    }
	    else {
		int portNumber;
		InetAddress externIP;
		if(serverActive || pimped){
		    portNumber = randPort();
		    if(pimped){
			transferAnonClient.setDCStack("phoebus");
			System.out.println("DCStack set for phoebus. Anonymous. server Active.");
		    }
		    HostPort hpc = transferAnonClient.setLocalPassive(portNumber, 0);
		    externIP = getIP();
		    HostPort hp = new HostPort(externIP, hpc.getPort());
		    transferAnonClient.setActive(hp);
		}
		else{
		    transferAnonClient.setPassive();
		    transferAnonClient.setLocalActive();
		}
		downloadTransfer = new DownloadThread(transferAnonClient, localFile, remoteFileName, remoteSize);
	    }
	    	
	    downloadTransfer.start();
	    localMonitor.run();
	    System.out.println("transfer successfully started");
	    	
	    String[] finished = new String[2];
	    finished[0] = localFile.getName();
	    finished[1] = Integer.toString(finishedJobs.size());
	    finishedJobs.add(finished);
	    if (firstTransfer == true) {
		firstTransfer = false;
	    }
	    return "success";
	}
	
	catch (Exception e) {
	    inProgress = false;
	    speed = 0;
	    progress = 0;
	    //System.out.println(e);
	    return(e.toString());
	}
    }//end download

    //this should also probably be switched to private.  only calling it from within here.
    /**
       Creates a UploadThread object and begins it's execution.  Also creates a RemoteFileMonitor object and being it's execution.
       @param remoteFile the full path of the remoteFile to upload to.
       @param localFile the File object that serves as the souce 
       @return "success" if the upload was successfully started.
    */
    public String upload(String remoteFile, File localFile) {
	inProgress = true;
	transferType = 1;
		
	transferName = localFile.getName();
		
	long localSize = localFile.length();
		
	try {
	    if(uploadClient!=null){
		remoteMonitor = new RemoteFileMonitor(remoteFile, localSize, uploadClient, cred);
	    }
	    else {
	       	remoteMonitor = new RemoteFileMonitor(remoteFile, localSize, uploadAnonClient, cred);
	    }
		
	}
	catch (Exception e) {
			
	}
	if(transferClient!=null){	
	    uploadTransfer = new UploadThread(transferClient, localFile, remoteFile);
	}
	else {
	    uploadTransfer = new UploadThread(transferAnonClient, localFile, remoteFile);
	}
		
	uploadTransfer.start();
	remoteMonitor.run();
		
	System.out.println("Upload successfully started");
		
	String[] finished = new String[2];
	finished[0] = localFile.getName();
	finished[1] = Integer.toString(finishedJobs.size());
	finishedJobs.add(finished);
		
	if (firstTransfer == true) {
	    firstTransfer = false;
	}
	if (firstUpload == true) {
	    firstUpload = false;
	}
	return "success";
		
    }
	
    public String cancel(String info) {
		
	System.out.println(info);
		
	int start = 0;
	int end = info.indexOf(" localFile:");
		
	String sub = info.substring(start, end);
	start = sub.indexOf(" ");
	String type = sub.substring(start+1);
	System.out.println(type);
	start = end+10;
		
	end = info.indexOf(" remoteFile:");
		
	sub = info.substring(start, end);
	start = sub.indexOf(" ");
	String local = sub.substring(start+1);
	System.out.println(local);
	start = end+11;
		
		
	end = info.indexOf(" transferCount:");
	sub = info.substring(start, end);
	start = sub.indexOf(" ");
	String remote = sub.substring(start+1);
	System.out.println(remote);

	start = end+14;
	end = info.length();
		
	sub = info.substring(start, end);
	start = sub.indexOf(" ");
	String count = sub.substring(start+1);
	System.out.println(count);
		
	String[] arg = new String[4];
	arg[0] = type;
	arg[1] = remote;
	arg[2] = local;
	arg[3] = count;
		
	if ( compareJobs(arg, currentTransfer)) {
	    try {
		System.out.println("stop the current");
		if (arg[0].compareTo("download") == 0) {
		    System.out.println(downloadTransfer.isAlive());
		    
		    if(transferClient!=null){
			transferClient.close(true);
			transferClient = null;
		    }
		    else {
			transferAnonClient.close(true);
			transferAnonClient = null;
		    }
		    setConnected(false);
		    transferReady=false;
		    downloadTransfer.cancel();
		    transferLoginThread.join();
		    transferLoginThread = null;
		    canceled=true;
		    System.out.println("test " + downloadTransfer.isAlive());
		    //transferClientLogin(serverStore);
		    localMonitor.stop();
				
		}
			
		else if (arg[0].compareTo("upload") == 0) {
		    System.out.println(uploadTransfer.isAlive());

		    if(transferClient!=null){
			transferClient.close(true);
			transferClient = null;
		    }
		    else {
			transferAnonClient.close(true);
			transferAnonClient = null;
		    }

		    setConnected(false);
		    transferReady=false;
	    			
	    	
		    transferLoginThread.join();
		    transferLoginThread = null;
		    canceled=true;
		    System.out.println(uploadTransfer.isAlive());
		    uploadTransfer.stop();
		}
	    }
	    catch (Exception e) {
		System.out.println(e);	
	    }
	}
		
	else {
		
	    for(int i=0; i<transferQueue.size(); i++) {
		if (compareJobs(arg, transferQueue.get(i))) {
		    System.out.println("remove index: " + i);	
		    transferQueue.remove(i);
		    break;
		}
	    }	
		
	}
	//if not try to remove it from the queue
		
	//otherwise return failed?
	return "success";
    }
	
    /**
       Takes two String[] detailing jobs, returns whether or not they're equal.
    */
    public boolean compareJobs(String[] job1, String[] job2) {
	if ((job1[0].compareTo(job2[0]) == 0) && (job1[1].compareTo(job2[1]) == 0) && (job1[2].compareTo(job2[2]) == 0) && (job1[3].compareTo(job2[3]) == 0)) {
	    return true;	
	}
	return false;
    }
    /**
       Checks to see if a transfer is currently in progress.
    */
    public boolean transferInProgress() {
	System.out.println("trans in prog called");
    	if(transferType == 0) {
	    System.out.println("tranferType == 0");
	    if(downloadTransfer != null) {
		inProgress = (!downloadTransfer.transferComplete());
		System.out.println("inProgress = " +inProgress);
		if (!inProgress) {
		    localMonitor.stop();	
		}
		return inProgress;
	    }
	    else
	    	return false;
    	}
    	else if (transferType == 1) {
	    if(uploadTransfer != null) {
		inProgress = (!uploadTransfer.transferComplete());
		//if it's done
		if (!inProgress) {
		    //System.out.println("stopping the monitor");
		    remoteMonitor.stop();
		}
		return inProgress;
	    }
	    else
		return false;
    	}
    	else
	    return false;
    }

    /**
       Returns the last completed transfer.
       return a string array containing the name of the transfer type (upload or download), the remote file name, and the local file name.  null if no file has been transferred
    */
    public String[] getLastCompletedTransfer() {
	if (finishedJobs.size() > 0) {
	    return finishedJobs.getLast();
	}
	else {
	    return null;
	}
    }

    /**
       return the name of the last transfer.
    */
    public String getTransferName() {
	return transferName;
    }

    /**
       Gets the speed of the current transfer in kb/s.
       @return the speed.  -1 if the monitor has not been defined.
    */
    public double getSpeed() {
    
	if (transferType == 0) {
	    if (localMonitor != null) {
		speed = localMonitor.getSpeed();
		return speed;
	    }
	    else {
		return -1;
	    }
	}
	else if (transferType == 1) {
	    if (remoteMonitor != null) {
		speed = remoteMonitor.getSpeed();
		return speed;
	    }
	    else {
		return -1;
	    }
	}
	else {
	    return -1;
	}
    }

    /**
       Gets the percent complete of the current transfer.
       @return the progress.  -1 if the monitor wasn't defined.
    */
    public double getProgress() {
	if (transferType == 0) {
	    if (localMonitor != null) {
		progress = localMonitor.getProgress();
		return progress;
	    }
	    else {
		return -1;
	    }
	}
	else if (transferType == 1) {
	    if (remoteMonitor != null) {
		progress = remoteMonitor.getProgress();
		return progress;
	    }
	    else {
		return -1;
	    }
	}
	else {
	    return -1;
	}
    }


    /**
       Changes the info clients current directory.
       @param dir the destination directory.
       @return "success" if successfully able to change dir.
    */
    public String changeDir(String dir) {

	try {
	    if(infoClient!=null){
		infoClient.changeDir(dir);
	    }
	    else{
		infoAnonClient.changeDir(dir);
	    }
	    return "success";
	}

	catch(Exception e) {
	    System.out.println("Failed changing dir");
	    e.printStackTrace();
	    return(e.toString());
	}
    }

    /**
       Gets the info clients current directory
       @return the current dir or "failed" if there was a problem.
    */
    public String getCurrentDir() {

	try {
	    if(infoClient!=null){
		return infoClient.getCurrentDir();
	    }
	    else{
		return infoAnonClient.getCurrentDir();
	    }
	}

	catch(Exception e) {
	    return "failed";
	}
    }

    /**
       Changes the info client to the parent dir of the current dir.
       @return "success" if successful
    */
    public String goUpDir() {
	
	try {
	    if(infoClient!=null){
		infoClient.goUpDir();
	    }
	    else{
		infoAnonClient.goUpDir();
	    }
	    return "success";
	}
	
	catch(Exception e) {
	    System.out.println("Failed going up dir");
	    e.printStackTrace();
	    return "failed";
	}
    }

    /**
       Need to close all the clients, and set everything to null
       So they can be reinitialized on the next connection
       @return "success" if successful.
    */
    public String close() {
		
	try {
	    System.out.println("starting close");
	    if(infoClient!=null){
		infoClient.close(true);
	    }
	    else{
		infoAnonClient.close(true);
	    }
	    System.out.println("info client closed");
	    if (! canceled) {
		if(transferClient!=null){
		    transferClient.close(true);
		}
		else{
		    transferAnonClient.close(true);
		}
	    }
	    System.out.println("Transfer client closed");
	    if(uploadClient!=null){
		uploadClient.close(true);
	    }
	    else {
		uploadAnonClient.close(true);
	    }
	    System.out.println("upload client closed");
			
	    infoClient = null;
	    infoAnonClient=null;
	    transferClient = null;
	    transferAnonClient = null;
	    uploadClient = null;
	    uploadAnonClient = null;
			
	    setConnected(false);
	    System.out.println("new closed");
	    infoReady=false;
	    transferReady=false;
	    uploadReady=false;
	    	
	    transferLoginThread.join();
	    transferLoginThread = null;
	    uploadLoginThread.join();
	    uploadLoginThread = null;
	    loginComponent.join();
	    loginComponent = null;
	    
	    inProgress = false;

	    return "success";
	}
	catch (Exception e) {
	    return e.toString();
	}
    }
    
    public void delete(String filePath, boolean dir) {
    	try {
	    if(dir) {
		if(infoClient!=null){
		    infoClient.deleteDir(filePath);
		}
		else{
		    infoAnonClient.deleteDir(filePath);
		}
	    }
	    else{
		if(infoClient!=null){
		    infoClient.deleteFile(filePath);
		}
		else {
		    infoAnonClient.deleteFile(filePath);
		}
	    }
    	}
    	catch (Exception e) {
	    System.out.println(e);	
    	}
    }
    
    //returns a random open port from 30000 to 50000
    //yea the range could be wider but... why get greedy?
    private int randPort() throws java.io.IOException{
	Random portgen = new Random();
	boolean portTaken=false;
	ServerSocket socket = null;
	int portNumber;
	do {
	    portNumber = portgen.nextInt(20000)+30000;
	    try {
		socket = new ServerSocket(portNumber);
	    } catch (IOException e) {
		portTaken = true;
	    } finally { 
		// Clean up
		if (socket != null) socket.close(); 
	    }
	} while (portTaken);
	return portNumber;
    }

    private InetAddress getIP() throws java.net.SocketException{
	InetAddress externIP = null;
	Enumeration e = NetworkInterface.getNetworkInterfaces();
	while(e.hasMoreElements()){
	    NetworkInterface ni = (NetworkInterface) e.nextElement();
	    Enumeration e2 = ni.getInetAddresses();
	    while(e2.hasMoreElements()){
		InetAddress ip = (InetAddress) e2.nextElement();
		if(!ni.getName().contains("lo")&&!ip.toString().contains(":")){
		    externIP = ip;
		}
	    }
	}
	return externIP;
    }

    
}
